// 定义一些列 HTTP Request 相关的对象和处理方法

package cf

import (
	"bytes"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"time"
)

// 用于用户函数执行出错时，返回错误响应
type InvokeResponse struct {
	Error *InvokeResponse_Error
}

type InvokeResponse_Error struct {
	Message    string                             `json:"errorMessage"`
	Type       string                             `json:"errorType"`
	StackTrace []*InvokeResponse_Error_StackFrame `json:"stackTrace,omitempty"`
	ShouldExit bool                               `json:"-"`
}

func (e InvokeResponse_Error) Error() string {
	return fmt.Sprintf("%#v", e)
}

func (e InvokeResponse_Error) ToJson() string {
	res, err := json.MarshalIndent(e, "", " ")
	if err != nil {
		log.Fatalln(err)
	}
	return string(res)
	// return fmt.Sprintf("%#v", e)
}

type InvokeResponse_Error_StackFrame struct {
	Path  string `json:"path"`
	Line  int32  `json:"line"`
	Label string `json:"label"`
}

// 用于传入 http handler，接受用户函数返回信息，供外层统一处理，需实现 http.ResponseWriter 接口
type fcResponse struct {
	status      int
	wroteHeader bool
	header      http.Header
	body        bytes.Buffer
}

func newFcResponse() *fcResponse {
	return &fcResponse{
		header: http.Header{},
		body:   bytes.Buffer{},
	}
}

func (r *fcResponse) Header() http.Header {
	return r.header
}

func (r *fcResponse) Write(p []byte) (n int, err error) {
	if !r.wroteHeader {
		r.WriteHeader(http.StatusOK)
	}
	return r.body.Write(p)
}

func (r *fcResponse) WriteHeader(statusCode int) {
	if r.wroteHeader {
		return
	}
	r.wroteHeader = true // 保证 statusCode 仅赋值一次
	r.status = statusCode
	if r.header.Get("Date") == "" {
		r.header.Set("Date", time.Now().UTC().Format(http.TimeFormat))
	}
}

// 向客户端返回 fcResponse 传入的内容
func WriteResponse(w http.ResponseWriter, resp *fcResponse) {
	// 写入头部信息
	for key, values := range resp.header {
		for _, value := range values {
			w.Header().Add(key, value)
		}
	}
	w.WriteHeader(resp.status)
	// 写入响应体
	w.Write(resp.body.Bytes())
}
